package com.vincent.jvmtest.bootstrap;

import com.alibaba.fastjson.JSON;
import com.vincent.jvmtest.config.EnableRefresh;
import com.vincent.jvmtest.config.TestProperties;
import com.vincent.jvmtest.util.RefUtils;
import com.vincent.jvmtest.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ClassUtils;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * @author vincent
 * @date 2019/5/16
 * @description
 */
@Component
@Slf4j
public class Bootstrap implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
//        Map<String, Object> bean = SpringUtil.getBeanWithAnnotation(ConfigurationProperties.class);
//        bean.forEach((key, b) -> {
//            String[] split = key.split("-");
//            log.info("config prefix = {}", split[0]);
//            log.info("config className = {}", split[1]);
//            try {
//                Class<?> clz = ClassUtils.getClass(split[1]);
//                TestProperties testProperties = new TestProperties();
//                testProperties.setIp("127.0.0.1");
//                testProperties.setPort("8080");
//
//                List<String> annotations = RefUtils.getAnnotations(clz);
//                log.info(annotations.toString());
////                ConfigurationProperties annotation = clz.getAnnotation(ConfigurationProperties.class);
////                String prefix = annotation.prefix();
//                // 判断是否允许动态刷的bean
//                if (annotations.contains("EnableRefresh")) {
//                    log.info("enable refresh");
//                }
//                // 假设消费到需要刷新的配置prefix是test,然后动态刷新这个配置的属性
//                if (split[0].equals("test")) {
//                    // 获取所有属性
//                    Field[] fields = clz.getDeclaredFields();
//                    // 获取实体
//                    Object o = JSON.parseObject(JSON.toJSONString(testProperties), clz);
//                    // 遍历属性
//                    for (Field field : fields) {
//                        // 允许私有属性也可以设置值
//                        field.setAccessible(true);
//                        // 获取属性值
//                        Object value = field.get(o);
//                        if (clz.isInstance(b)) {
//                            Object cast = clz.cast(b);
//                            // 设置属性值
//                            RefUtils.setField(clz, field.getName(), cast, value);
//                        }
//                    }
//
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        });
//        TestProperties pro = SpringUtil.getBean(TestProperties.class);
//        log.info(pro.toString());
        TestProperties testProperties = new TestProperties();
        testProperties.setIp("127.0.0.1");
        testProperties.setPort("8080");
        String json = JSON.toJSONString(testProperties);
        Map<String, Object> beanWithAnnotation = SpringUtil.getBeanWithAnnotation(EnableRefresh.class);
        beanWithAnnotation.forEach((name, obj) -> {
            String[] split = name.split("-");
            String className = split[split.length - 1];
            try {
                Class<?> clz = ClassUtils.getClass(className);
                List<String> annotations = RefUtils.getAnnotations(clz);
                if (annotations.contains("ConfigurationProperties")) {
                    ConfigurationProperties annotation = clz.getAnnotation(ConfigurationProperties.class);
                    String prefix = annotation.prefix();
                    if (prefix.equals("vincent-test")) {
                        // 获取所有属性
                        Field[] fields = clz.getDeclaredFields();
                        // 获取实体
                        Object o = JSON.parseObject(json, clz);
                        // 遍历属性
                        for (Field field : fields) {
                            // 允许私有属性也可以设置值
                            field.setAccessible(true);
                            // 获取属性值
                            Object value = field.get(o);
                            if (clz.isInstance(obj)) {
                                Object cast = clz.cast(obj);
                                // 设置属性值
                                RefUtils.setField(clz, field.getName(), cast, value);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        TestProperties pro = SpringUtil.getBean(TestProperties.class);
        log.info(pro.toString());
    }
}
